/* Bug in MIDL: Comment out the three references to _maxcount_test in the component_p.c file */

// client.cpp
#define _WIN32_DCOM
#include <iostream.h>
#include <stdio.h>
#include "Component\component.h"

void main()
{
	CoInitialize(NULL);
		
	ITest* pTest;
	CoCreateInstance(CLSID_TestIDL, NULL, CLSCTX_LOCAL_SERVER, IID_ITest, (void**)&pTest);

	// HRESULT SquareInteger([in] int myInteger, [out] int* square);
	int square;
	pTest->SquareInteger(6, &square);
	cout << "SquareInteger: 6^2 = " << square << endl;

	// HRESULT SumOfIntegers1([in] int myIntegers[5], [out] int* sum);
	int total1;
	int integers[5] = { 1, 2, 3, 4, 5 };
	pTest->SumOfIntegers1(integers, &total1);
	cout << "SumOfIntegers1: 1 + 2 + 3 + 4 + 5 = " << total1 << endl;

	// HRESULT SumOfIntegers2([in] int cMax, [in, size_is(cMax)] int* myIntegers, [out] int* sum);
	int total2;
	pTest->SumOfIntegers2(5, integers, &total2);
	cout << "SumOfIntegers2: 1 + 2 + 3 + 4 + 5 = " << total2 << endl;

	/* typedef struct tagSUM_STRUCT
	{
		int cMax;
		[size_is(cMax)] int* myIntegers;
	} SUM_STRUCT; */
	// HRESULT SumOfIntegers3([in] SUM_STRUCT* myIntegers, [out] int* sum);
	int total3;
	SUM_STRUCT mystruct;
	mystruct.cMax = 5;
	mystruct.myIntegers = integers;
	pTest->SumOfIntegers3(&mystruct, &total3);
	cout << "SumOfIntegers3: 1 + 2 + 3 + 4 + 5 = " << total3 << endl;

	// HRESULT SumOfIntegers4([in] int cFirst, [in] int cActual, [in, first_is(cFirst), length_is(cActual)] int* myIntegers[7], [out] int* sum);
	int sum = 0;
	int someInts[7];
	someInts[3] = 4; someInts[4] = 5; someInts[5] = 6;
	HRESULT hr = pTest->SumOfIntegers4(4, 3, (int**)someInts, &sum);
	cout << "SumOfIntegers4: 4 + 5 + 6 = " << sum << endl;
	printf("hr = %0x\n", hr);

	// HRESULT ProduceIntegers1([in] int cMax, [out, size_is(cMax)] int* myIntegers);
	int array[5];
	pTest->ProduceIntegers1(5, array);
	for(int i = 0; i < 5; i++)
		cout << "ProduceIntegers1: " << array[i] << endl;

	// HRESULT ProduceIntegers2([out] int* pcActual, [out, length_is(*pcActual)] int myIntegers[4096]);
	int how_many_did_we_get = 0;
	int myIntegers[4096];
	pTest->ProduceIntegers2(&how_many_did_we_get, myIntegers);
	cout << "ProduceIntegers2: " << how_many_did_we_get << " integers returned" << endl;

	// HRESULT SendReceiveIntegers([in, out] int* pcActual, [in, out, length_is(*pcActual)] int myIntegers[4096]);
	int num_integers = 5;
	int some_ints[4096] = { 0, 1, 2, 3, 4 };
	pTest->SendReceiveIntegers(&num_integers, some_ints);
	cout << "SendReceiveIntegers: " << num_integers << " integers returned" << endl;

	// HRESULT ProduceIntegers3([in] int cMax, [out] int* pcActual, [out, size_is(cMax), length_is(*pcActual)] int* myIntegers);
	how_many_did_we_get = 0;
	int more_ints[6];
	pTest->ProduceIntegers3(6, &how_many_did_we_get, more_ints);
	cout << "ProduceIntegers3: " << how_many_did_we_get << " integers returned" << endl;

	// HRESULT SendString1([in] int cLength, [in, size_is(cLength)] wchar_t* myString);
	wchar_t wszHello1[] = L"Hello COM";
	pTest->SendString1(wcslen(wszHello1), wszHello1);

	// HRESULT SendString2([in, string] wchar_t* myString);
	wchar_t wszHello2[] = L"Hello COM";
	pTest->SendString2(wszHello2);

	// HRESULT SendReceiveString1([in, out, string] wchar_t* myString);
	wchar_t wszHello[256] = L"Hello COM";
	pTest->SendReceiveString1(wszHello);
	wprintf(L"SendReceiveString1: %s\n", wszHello);

	// HRESULT SendReceiveString2([in] int cMax, [in, out, string, size_is(cMax)] wchar_t* myString);
	wchar_t wszAString[256] = L"Hello COM";
	pTest->SendReceiveString2(256, wszAString);
	wprintf(L"Received string: %s\n", wszAString);

	// HRESULT SendReceiveString3([in, out, string] wchar_t** myString);
	wchar_t* wszHello3 = L"Hello COM";
	wchar_t* myString = (wchar_t*)CoTaskMemAlloc((wcslen(wszHello3)+1)*sizeof(wchar_t));
	wcscpy(myString, wszHello3);
	pTest->SendReceiveString3(&myString);
	wprintf(L"SendReceiveString3: %s\n", myString);
	CoTaskMemFree(myString);

	// HRESULT SendInteger([in] int** test);
	int an_int = 7;
	int *pint1 = &an_int;
	pTest->SendInteger(&pint1);

	// HRESULT SendIntegers1([in, size_is(, 2)] int** test);
	int test1[2] = { 10, 20 };
	int* pint2 = (int*)&test1;
	pTest->SendIntegers1(&pint2);

	// HRESULT SendIntegers2([in, size_is(3, )] int** test);
	int* test2[3];
	int a1 = 3, a2 = 7, a3 = 9;
	test2[0] = &a1;
	test2[1] = &a2;
	test2[2] = &a3;
	pTest->SendIntegers2(test2);

	// HRESULT SendIntegers3([in, size_is(3, 2)] int** test);
	int testA[2] = { 1, 2 };
	int testB[2] = { 3, 4 };
	int testC[2] = { 5, 6 };
	int* test3[3];
	test3[0] = testA;
	test3[1] = testB;
	test3[2] = testC;
	pTest->SendIntegers3(test3);

	pTest->Release();
	CoUninitialize();
}